﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using YArchitech.Revit;
using YJKRevitKernel.ElementSearchUtility.LinkDocumentSuite;
using YJKRevitStairs.StairsModel.CommonUnit;

namespace YJKPatternSign.StairsClearHeightDimension
{
	public class FloorSearchManager
	{
		public FloorSearchManager(Autodesk.Revit.DB.Document doc)
		{
			this.m_rvtDoc = doc;
			this.InitData();
		}

		private void InitData()
		{
			new List<Element>();
			foreach (Element element in FloorSearchManager.FilterElemByKind(new ElementClassFilter(typeof(Floor)), this.m_rvtDoc))
			{
				Floor floor = element as Floor;
				if (floor != null)
				{
					double num = 0.0;
					ElementId levelId = floor.LevelId;
					Level level = this.m_rvtDoc.GetElement(levelId) as Level;
					if (level != null)
					{
						num += level.Elevation;
					}
					Parameter parameter = floor.GetParameter("自标高的高度偏移");
					if (parameter != null)
					{
						num += parameter.AsDouble();
					}
					if (!this.m_dValToFloor.ContainsKey(num))
					{
						List<Floor> list = new List<Floor>();
						list.Add(floor);
						this.m_dValToFloor.Add(num, list);
					}
					else
					{
						this.m_dValToFloor[num].Add(floor);
					}
				}
			}
		}

		private List<Floor> GetSolidInterSectionFloor(Solid solid)
		{
			List<Floor> list = new List<Floor>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_rvtDoc);
			filteredElementCollector.OfClass(typeof(Floor));
			ElementIntersectsSolidFilter elementIntersectsSolidFilter = new ElementIntersectsSolidFilter(solid);
			List<Element> arFloor = filteredElementCollector.WherePasses(elementIntersectsSolidFilter).ToElements().ToList<Element>();
			SortedDictionary<double, List<Floor>> sortedDictionary = this.CreateFloorDic(arFloor);
			if (sortedDictionary.Count > 0)
			{
				foreach (KeyValuePair<double, List<Floor>> keyValuePair in sortedDictionary)
				{
					list.AddRange(keyValuePair.Value);
				}
			}
			return list;
		}

		private List<StairsLanding> GetSolidInterSectionLanding(Solid solid)
		{
			List<StairsLanding> list = new List<StairsLanding>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_rvtDoc);
			filteredElementCollector.OfClass(typeof(Stairs));
			ElementIntersectsSolidFilter elementIntersectsSolidFilter = new ElementIntersectsSolidFilter(solid);
			List<Element> arStairs = filteredElementCollector.WherePasses(elementIntersectsSolidFilter).ToElements().ToList<Element>();
			SortedDictionary<double, List<StairsLanding>> sortedDictionary = this.CreateLandingDic(arStairs);
			if (sortedDictionary.Count > 0)
			{
				foreach (KeyValuePair<double, List<StairsLanding>> keyValuePair in sortedDictionary)
				{
					list.AddRange(keyValuePair.Value);
				}
			}
			return list;
		}

		private double GetFloorAbsoluteHeight(Floor floor)
		{
			double result = 0.0;
			if (floor != null)
			{
				double num = 0.0;
				ElementId elementId = floor.GetParameter(BuiltInParameter.LEVEL_PARAM).AsElementId();
				Level level = this.m_rvtDoc.GetElement(elementId) as Level;
				if (level.IsValidObject)
				{
					num = level.Elevation;
				}
				double num2 = floor.GetParameter(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM).AsDouble();
				result = num + num2;
			}
			return result;
		}

		private SortedDictionary<double, List<Floor>> CreateFloorDic(List<Element> arFloor)
		{
			SortedDictionary<double, List<Floor>> sortedDictionary = new SortedDictionary<double, List<Floor>>();
			foreach (Element element in arFloor)
			{
				if (element is Floor)
				{
					Floor floor = element as Floor;
					if (floor != null)
					{
						double floorAbsoluteHeight = this.GetFloorAbsoluteHeight(floor);
						if (sortedDictionary.Keys.Contains(floorAbsoluteHeight))
						{
							sortedDictionary[floorAbsoluteHeight].Add(floor);
						}
						else
						{
							sortedDictionary.Add(floorAbsoluteHeight, new List<Floor>
							{
								floor
							});
						}
					}
				}
			}
			return sortedDictionary;
		}

		private SortedDictionary<double, List<StairsLanding>> CreateLandingDic(List<Element> arStairs)
		{
			SortedDictionary<double, List<StairsLanding>> sortedDictionary = new SortedDictionary<double, List<StairsLanding>>();
			List<Element> list = new List<Element>();
			foreach (Element element in arStairs)
			{
				Stairs stairs = element as Stairs;
				if (stairs != null)
				{
					foreach (ElementId elementId in (stairs.GetStairsLandings() as List<ElementId>))
					{
						Element element2 = this.m_rvtDoc.GetElement(elementId);
						if (element2 != null)
						{
							list.Add(element2);
						}
					}
				}
			}
			foreach (Element element3 in list)
			{
				if (element3 is StairsLanding)
				{
					StairsLanding stairsLanding = element3 as StairsLanding;
					if (stairsLanding != null)
					{
						double absoluteElevation = StairsLandingParamManager.GetAbsoluteElevation(stairsLanding);
						if (sortedDictionary.Keys.Contains(absoluteElevation))
						{
							sortedDictionary[absoluteElevation].Add(stairsLanding);
						}
						else
						{
							sortedDictionary.Add(absoluteElevation, new List<StairsLanding>
							{
								stairsLanding
							});
						}
					}
				}
			}
			return sortedDictionary;
		}

		public List<XYZ> GetSpecifyFloorIntersection(double dHeight, Line interLine, double dTol = 0.0)
		{
			List<XYZ> list = new List<XYZ>();
			foreach (KeyValuePair<double, List<Floor>> keyValuePair in this.m_dValToFloor)
			{
				if (Math.Abs(keyValuePair.Key - dHeight) < dTol)
				{
					foreach (Floor element in keyValuePair.Value)
					{
						List<XYZ> stairsRunLandSortedPoints = new CurveIntersection(element, interLine).GetStairsRunLandSortedPoints(CurveIntersection.IntersectionType.IT_SOLID);
						if (stairsRunLandSortedPoints.Count > 0)
						{
							list.AddRange(stairsRunLandSortedPoints);
							break;
						}
					}
				}
			}
			return list;
		}

		public XYZ GetSolidFloorNearUpPoint(XYZ ptStart, List<CurveLoop> arLoop, double dExtenalDist, XYZ vecDir)
		{
			XYZ result = null;
			Solid solid = GeometryCreationUtilities.CreateExtrusionGeometry(arLoop, vecDir, dExtenalDist);
			if (null != solid)
			{
				List<Floor> solidInterSectionFloor = this.GetSolidInterSectionFloor(solid);
				if (solidInterSectionFloor.Count > 0)
				{
					Floor floor = solidInterSectionFloor.Last<Floor>();
					if (floor != null)
					{
						double floorAbsoluteHeight = this.GetFloorAbsoluteHeight(floor);
						result = new XYZ(ptStart.X, ptStart.Y, floorAbsoluteHeight);
					}
				}
			}
			return result;
		}

		public XYZ GetSolidLandingNearUpPoint(XYZ ptStart, List<CurveLoop> arLoop, double dExtenalDist, XYZ vecDir)
		{
			XYZ result = null;
			Solid solid = GeometryCreationUtilities.CreateExtrusionGeometry(arLoop, vecDir, dExtenalDist);
			if (null != solid)
			{
				List<StairsLanding> solidInterSectionLanding = this.GetSolidInterSectionLanding(solid);
				if (solidInterSectionLanding.Count > 0)
				{
					StairsLanding stairsLanding = solidInterSectionLanding.Last<StairsLanding>();
					if (stairsLanding != null)
					{
						double absoluteElevation = StairsLandingParamManager.GetAbsoluteElevation(stairsLanding);
						result = new XYZ(ptStart.X, ptStart.Y, absoluteElevation);
					}
				}
			}
			return result;
		}

		public static List<Element> FilterElemByKind(ElementFilter filter, Autodesk.Revit.DB.Document doc)
		{
			FilteredElementCollectorLinkDocument filteredElementCollectorLinkDocument = new FilteredElementCollectorLinkDocument(doc);
			filteredElementCollectorLinkDocument.WherePass(filter);
			List<BaseLinkDocumentResultBean> list = filteredElementCollectorLinkDocument.ToBeans();
			List<Element> list2 = new List<Element>();
			foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean in list)
			{
				if (baseLinkDocumentResultBean.LinkeInstanceId == -1)
				{
					list2.Add(baseLinkDocumentResultBean.UseElement);
				}
				else if (baseLinkDocumentResultBean.LstParentRevitLinkInstance.Count <= 1)
				{
					CopyPasteOptions copyPasteOptions = new CopyPasteOptions();
					List<ElementId> list3 = new List<ElementId>();
					list3.Add(baseLinkDocumentResultBean.UseElement.Id);
					ICollection<ElementId> source = ElementTransformUtils.CopyElements(baseLinkDocumentResultBean.UseElement.Document, list3, doc, baseLinkDocumentResultBean.GetTotalTransform(), copyPasteOptions);
					list2.Add(doc.GetElement(source.First<ElementId>()));
				}
			}
			return list2;
		}

		private Dictionary<double, List<Floor>> m_dValToFloor = new Dictionary<double, List<Floor>>();

		private Document m_rvtDoc;
	}
}
